package com.ruoyi.common.utils.file;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.exception.file.InvalidExtensionException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ImagesFiler;
import com.ruoyi.common.utils.OssUtil;
import org.apache.commons.io.FilenameUtils;
import org.springframework.security.core.parameters.P;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

/**
 * 文件上传工具类
 *
 * @author ruoyi
 */
public class FileUploadUtils
{
    /**
     * 默认大小 50M
     */
    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;

    /**
     * 默认的文件名最大长度 100
     */
    public static final int DEFAULT_FILE_NAME_LENGTH = 100;


    public static final int TYPE_USER_PHOTOS = 0;//用户头像
    public static final int TYPE_PRODUCT_PHOTOS = 1;//商品的图片
    public static final int TYPE_TITLEMENU_PHOTOS = 2;//菜单
    public static final int TYPE_SECTION_PHOTOS = 3;//内容行
    public static final int TYPE_MATERIAL_PHOTOS = 4;//素材库
    public static final int TYPE_ADVERT_PHOTOS = 5;//广告
	public static final int TYPE_LUNBO_PHOTOS = 6;//轮播
	public static final int TYPE_ESTATE_PHOTOS = 7;//小区二维码
	public static final int TYPE_SHOP_PHOTOS = 8;//商家LOGO
	public static final int TYPE_PLATFORM_HELP_PHOTOS = 9;//帮助文档
	public static final int TYPE_DEVICE_PHOTOS = 10;//帮助文档

	public static final int TYPE_ACTIVE_PHOTOS = 11;//社区活动

	public static final int TYPE_PRODUCT_QRCODE = 12;//帮助文档
	public static final int TYPE_COUPONS = 13;//优惠券
	public static final int TYPE_TERMINALS = 14;//设备
	public static final int TYPE_PATROL_POINT = 15;//巡更点
	public static final int TYPE_CLEAN_AREA = 16;//巡更点
	public static final int TYPE_SET_MEAL = 17;//套餐活动
	public static final int TYPE_PROMOTER_MEAL = 18;//推广元

	public static final int TYPE_EVENT_POINT_QR = 19;//活动二维码

    public static final int TYPE_PRODUCT_ORDER = 28;//订单支付二维码
    public static final int TYPE_SURVEY_QR_CODE = 30;//调查问卷
	public static final int TYPE_NSH_QR_CODE = 31;
	public static final int TYPE_ESTATE_ROOM_PHOTOS = 32;//房屋二维码
	public static final int TYPE_COMMUNITY_ACTIVE = 33;//活动二维码
	public static final int TYPE_GUDING_ASSET_QR_CODE = 34;//固定资产二维码
	public static final int TYPE_YIDONG_ASSET_QR_CODE = 35;//移动资产二维码
	public static final int TYPE_CALL_RECORD = 36;//移动资产二维6
    public static final String USER_IMG_PREFIX  = "user/";
	public static final String PRODUCT_IMG_PREFIX  = "product/";
	public static final String TITLEMENU_IMG_PREFIX  = "titlemenu/";
	public static final String SECTION_IMG_PREFIX  = "section/";
	public static final String MATERIAL_IMG_PREFIX  = "material/";
	public static final String ADVERT_IMG_PREFIX  = "advert/";
	public static final String ACTIVE_IMG_PREFIX  = "active/";
	public static final String LUNBO_IMG_PREFIX  = "lunbo/";
	public static final String ESTATE_IMG_PREFIX  = "estate/";
	public static final String PATROL_POINT_IMG_PREFIX  = "patrol/";
	public static final String CLEAN_IMG_PREFIX  = "clean_area/";
	public static final String SHOP_IMG_PREFIX  = "shop/";
	public static final String PLATFORM_HELP_IMG_PREFIX  = "help/";
	public static final String PRODUCT_QRCODE_PREFIX  = "product_qr/";
	public static final String COUPONS_PREFIX  = "coupons/";
	public static final String TERMINALS_PREFIX  = "terminals/";
	public static final String SET_MEAL_PREFIX  = "set_meal/";
	public static final String PROMOTER_PREFIX  = "promoter/";
    public static final String PRODUCT_ORDER_PREFIX = "product_order/";
	public static final String NSH_QR_CODE = "nsh_qr/";
	public static final String ROOM_QR_CODE = "estate/room/";
	public static final String SURVEY_QR_CODE = "survey/";
	public static final String COMMUNITY_ACTIVE_QR_CODE = "communityActive/";
	public static final String EVETN_POINT_QR = "event/point/";
	public static final String GUDING_ASSET_QR_CODE = "asset/guding/";
	public static final String YIDONG_ASSET_QR_CODE = "asset/yidong/";
	private static final String CALL_RECORD_IMG_PREFIX  = "callrecord/";


	/**
	 * 获取  上传图片的 路径前缀
	 * @param upload_type
	 * @return
	 */
	public static String getUploadPrefix(int upload_type){
		String prefix = null;
		switch (upload_type) {
			case TYPE_USER_PHOTOS:
				prefix = USER_IMG_PREFIX;
				break;
			case TYPE_PRODUCT_PHOTOS:
				prefix = PRODUCT_IMG_PREFIX;
				break;
			case TYPE_TITLEMENU_PHOTOS:
				prefix = TITLEMENU_IMG_PREFIX;
				break;
			case TYPE_SECTION_PHOTOS:
				prefix = SECTION_IMG_PREFIX;
				break;
			case TYPE_MATERIAL_PHOTOS:
				prefix = MATERIAL_IMG_PREFIX;
				break;
			case TYPE_ADVERT_PHOTOS:
				prefix = ADVERT_IMG_PREFIX;
				break;
			case TYPE_LUNBO_PHOTOS:
				prefix = LUNBO_IMG_PREFIX;
				break;
			case TYPE_ESTATE_PHOTOS:
				prefix = ESTATE_IMG_PREFIX;
				break;
			case TYPE_SHOP_PHOTOS:
				prefix = SHOP_IMG_PREFIX;
				break;
			case TYPE_PLATFORM_HELP_PHOTOS:
				prefix = PLATFORM_HELP_IMG_PREFIX;
				break;
			case TYPE_ACTIVE_PHOTOS:
				prefix = ACTIVE_IMG_PREFIX;
				break;
			case TYPE_PRODUCT_QRCODE:
				prefix = PRODUCT_QRCODE_PREFIX;
				break;
			case TYPE_COUPONS:
				prefix = COUPONS_PREFIX;
				break;
			case TYPE_TERMINALS:
				prefix = TERMINALS_PREFIX;
				break;
			case TYPE_SET_MEAL:
				prefix = SET_MEAL_PREFIX;
				break;
			case TYPE_PROMOTER_MEAL:
				prefix = PROMOTER_PREFIX;
				break;
			case TYPE_PRODUCT_ORDER:
				prefix = PRODUCT_ORDER_PREFIX;
				break;
			case TYPE_NSH_QR_CODE:
				prefix = NSH_QR_CODE;
				break;
			case TYPE_PATROL_POINT:
				prefix = PATROL_POINT_IMG_PREFIX;
				break;
			case TYPE_CLEAN_AREA:
				prefix = CLEAN_IMG_PREFIX;
				break;
			case TYPE_ESTATE_ROOM_PHOTOS:
				prefix = ROOM_QR_CODE;
				break;
			case TYPE_SURVEY_QR_CODE:
				prefix = SURVEY_QR_CODE;
				break;
			case TYPE_COMMUNITY_ACTIVE:
				prefix = COMMUNITY_ACTIVE_QR_CODE;
				break;
			case TYPE_EVENT_POINT_QR:
				prefix = EVETN_POINT_QR;
				break;
			case TYPE_GUDING_ASSET_QR_CODE:
				prefix = GUDING_ASSET_QR_CODE;
				break;
			case TYPE_YIDONG_ASSET_QR_CODE:
				prefix = YIDONG_ASSET_QR_CODE;
				break;
			case TYPE_CALL_RECORD:
				prefix = CALL_RECORD_IMG_PREFIX;
				break;

		}
		return prefix;
	}

	/**
     * 默认上传的地址
     */
    private static String defaultBaseDir = RuoYiConfig.getProfile();

    public static void setDefaultBaseDir(String defaultBaseDir)
    {
        FileUploadUtils.defaultBaseDir = defaultBaseDir;
    }

    public static String getDefaultBaseDir()
    {
        return defaultBaseDir;
    }

    /**
     * 以默认配置进行文件上传
     *
     * @param file 上传的文件
     * @return 文件名称
     * @throws Exception
     */
    public static final String upload(MultipartFile file, Integer uploadType) throws IOException
    {
        try
        {
            return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION,uploadType);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }

    /**
     * 根据文件路径上传
     *
     * @param baseDir 相对应用的基目录
     * @param file 上传的文件
     * @return 文件名称
     * @throws IOException
     */
    public static final String upload(String baseDir, MultipartFile file, Integer uploadType) throws IOException
    {
        try
        {
            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, uploadType);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }

	/**
	 * 根据文件路径上传
	 *
	 * @param baseDir 相对应用的基目录
	 * @param file 上传的文件
	 * @return 文件名称
	 * @throws IOException
	 */
	public static final String uploadAppVersion(String baseDir, MultipartFile file, String version) throws IOException
	{
		try
		{
			return uploadAppVersion(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, version);
		}
		catch (Exception e)
		{
			throw new IOException(e.getMessage(), e);
		}
	}


	/**
	 * 文件上传
	 *
	 * @param baseDir 相对应用的基目录
	 * @param file 上传的文件
	 * @param allowedExtension 上传文件类型
	 * @return 返回上传成功的文件名
	 * @throws FileSizeLimitExceededException 如果超出最大大小
	 * @throws FileNameLengthLimitExceededException 文件名太长
	 * @throws IOException 比如读写文件出错时
	 * @throws InvalidExtensionException 文件校验异常
	 */
	public static final String uploadAppVersion(String baseDir, MultipartFile file, String[] allowedExtension,String version)
		throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
		InvalidExtensionException
	{
		int fileNamelength = file.getOriginalFilename().length();
		if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
		{
			throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
		}

		assertAllowed(file, allowedExtension);

		String fileName = getAppVersionName(file,version);
		String prefix = getUploadPrefix(14);
		File desc = getAbsoluteFile(baseDir + "/" + prefix, fileName);

		desc = FileUtil.touch(desc);
		FileUtil.writeFromStream(file.getInputStream(), desc);

		OssUtil.uploadObs(file.getInputStream(),fileName,14);

		String pathFileName = prefix + fileName;//  getPathFileName(baseDir, fileName);
		return pathFileName;
	}

    /**
     * 文件上传
     *
     * @param baseDir 相对应用的基目录
     * @param file 上传的文件
     * @param allowedExtension 上传文件类型
     * @return 返回上传成功的文件名
     * @throws FileSizeLimitExceededException 如果超出最大大小
     * @throws FileNameLengthLimitExceededException 文件名太长
     * @throws IOException 比如读写文件出错时
     * @throws InvalidExtensionException 文件校验异常
     */
    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension,Integer uploadType)
            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
            InvalidExtensionException {
        int fileNamelength = file.getOriginalFilename().length();
        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
        }

        assertAllowed(file, allowedExtension);

        String fileName = extractFilename(file);
        String prefix = getUploadPrefix(uploadType);
		System.out.println("path: " + baseDir + "/" + prefix);
		System.out.println("fileName: " + fileName);
        File desc = getAbsoluteFile(baseDir + "/" + prefix, fileName);

		desc = FileUtil.touch(desc);
		FileUtil.writeFromStream(file.getInputStream(), desc);

		String extension = getExtension(file);

		if(!extension.equals("mp4")){
			try{
				ImagesFiler.imageResize(baseDir + "/" + prefix + fileName,baseDir + "/" + prefix + fileName);
			}catch (Exception e){
				e.printStackTrace();
			}
		}

		OssUtil.uploadObs(file.getInputStream(),fileName, uploadType);

        String pathFileName = prefix + fileName;//  getPathFileName(baseDir, fileName);
		System.out.println("pathFileName:" + pathFileName);
        return pathFileName;
    }

	/**
	 * 编码文件名
	 */
	public static final String getAppVersionName(MultipartFile file, String version)
	{
		String fileName = "";
		String extension = getExtension(file);
		fileName = DateUtils.datePath() + "/AppVersion_" + version + "." + extension;
		return fileName;
	}


    /**
     * 编码文件名
     */
    public static final String extractFilename(MultipartFile file)
    {
        String fileName = "";
        String extension = getExtension(file);
        fileName = DateUtils.datePath() + "/" + IdUtil.fastUUID() + "." + extension;
        return fileName;
    }

    private static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
    {
        File desc = new File(uploadDir + File.separator + fileName);

        if (!desc.exists())
        {
            if (!desc.getParentFile().exists())
            {
                desc.getParentFile().mkdirs();
            }
        }
        return desc;
    }

    private static final String getPathFileName(String uploadDir, String fileName) throws IOException
    {
        int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
        String currentDir = StrUtil.subSuf(uploadDir, dirLastIndex);
        String pathFileName = Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
        return pathFileName;
    }



    /**
     * 文件大小校验
     *
     * @param file 上传的文件
     * @return
     * @throws FileSizeLimitExceededException 如果超出最大大小
     * @throws InvalidExtensionException
     */
    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, InvalidExtensionException {
        long size = file.getSize();
        if (DEFAULT_MAX_SIZE != -1 && size > DEFAULT_MAX_SIZE) {
            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
        }

        String fileName = file.getOriginalFilename();
        String extension = getExtension(file);
        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension)) {
            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION) {
                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
                        fileName);
            }
            else
            {
                throw new InvalidExtensionException(allowedExtension, extension, fileName);
            }
        }

    }

    /**
     * 判断MIME类型是否是允许的MIME类型
     *
     * @param extension
     * @param allowedExtension
     * @return
     */
    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
    {
        for (String str : allowedExtension)
        {
            if (str.equalsIgnoreCase(extension))
            {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取文件名的后缀
     *
     * @param file 表单文件
     * @return 后缀名
     */
    public static final String getExtension(MultipartFile file)
    {
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        if (Validator.isEmpty(extension))
        {
            extension = MimeTypeUtils.getExtension(file.getContentType());
        }
        return extension;
    }
}
